/*************************************
 *                                   *
 *         Alex & Umit               *
 *                                   *
 ************************************/

public class HashTable
{
	
	//attributen van HashTable
    private Item[] data;
    private int capacity;
    private int size;
    private static final Item AVAILABLE = new Item("Available", null);

    private final String NO_SUCH_KEY = "NO_SUCH_KEY";
    private int sumGet = 0;
    private int sumPut = 0;

    //constructor
    //heeft een lege HashTable gemaakt met capacity = c
    public HashTable(int c)
    {
        capacity = c;
        data = new Item[c];
    }

    //retourneert het aantal items
    public int size()
    {
        return size;
    }

    //retourneert element als het item (key,element) in de HashTable voorkomt
    //retourneert anders null
    public Object get(String key)
    {
        sumGet++;
        int i = hash(key);
        int p = 0;

        while (p != size)
        {
            Item c = data[i];

            if (c == null)
            {
                return NO_SUCH_KEY;
            }
            else if (c.key().equals(key))
            {
                return c.element();
            }
            else
            {
                sumGet++;
                i = (i + 1) % capacity;
                p++;
            }
        }
        return NO_SUCH_KEY;
    }

    //pre: key is niet null
    //post: heeft Item(key,element) aan de HashTable toegevoegd mbv linear probing
    public void put(String key, Object element)
    {
        sumPut++;

        if (key == null)
            return;
        // throw exception if it's full?
        if (size == capacity)
            return;

        int i = hash(key);
        int p = 0;

        while (p != capacity)
        {
            // handle empty or no such key
            if (data[i] == null || data[i] == AVAILABLE)
            {
                data[i] = new Item(key, element);
                size++;
                return;
            }

            sumPut++;
            i = (i + 1) % capacity;
            p++;
        }
    }

    //post: verwijdert item (key,element) en retourneert element als dit item in de HashTable voorkomt, 
	//retourneert anders null
    public Object remove(String key)
    {
        int i = hash(key);
        int p = 0;
        Object tmp;

        while (p != size)
        {
            Item c = data[i];

            if (c == null)
                return NO_SUCH_KEY;
            else if (c.key().equals(key))
            {
                tmp = c.element();
                data[i] = AVAILABLE;
                size--;
                return tmp;
            }
            
            i = (i + 1) % capacity;
            p++;
        }

        return NO_SUCH_KEY;
    }

    //toString methode
    //retourneert een String representatie van de HashTable
    public String toString()
    {
	StringBuilder sb = new StringBuilder(size);

        sb.append("Hashtable of size: " + size + "\n");
        for (int i = 0; i < data.length; i++)
        {
            if (data[i] != null)
                sb.append("[" + i + "] " + data[i] + "\n");
        }

        return sb.toString();
    }

    private int hash(String key)
    {
        return Math.abs(key.hashCode() % capacity);
    }

	//drukt de waarden van sumPut en sumGet af
    public void tellingen()
    {
        System.out.printf("sumGet: %d, sumPut: %d\n", sumGet, sumPut);
    }
}
